package com.diaohw.platform.framework.openfeign;

import cn.hutool.core.io.IoUtil;
import com.diaohw.platform.common.exception.GlobalException;
import com.diaohw.platform.common.obj.Result;
import com.diaohw.platform.common.obj.thread.RequestThread;
import com.diaohw.platform.common.util.JacksonUtil;
import com.diaohw.platform.common.util.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import feign.RequestInterceptor;
import feign.Retryer;
import feign.Util;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.MultiValueMap;

import java.util.List;
import java.util.Map;

import static feign.Util.UTF_8;

/**
 * @author 刁海文
 * @Remark
 * @since 2023/6/15 21:26
 */
public class GlobalFeignResultConfig {

    private final String RESULT_TYPE_NAME = Result.class.getTypeName();

    /**
     * 请求失败充实次数
     */
    @Bean
    public Retryer feignRetryer() {
        return new Retryer.Default();
    }


    @Bean
    public Encoder feignEncoder() {
        return new SpringEncoder(() -> new HttpMessageConverters(createJsonConverter()));
    }

    /**
     * 配置解码器
     */
    @Bean
    public Decoder feignDecoder() {
        return (response, type) -> {
            if (type.getTypeName().equals("byte[]")) {
                return IoUtil.readBytes(response.body().asInputStream());
            }
            //对结果进行转换
            String str = Util.toString(response.body().asReader(UTF_8));
            if (type.getTypeName().startsWith(RESULT_TYPE_NAME)) {
                return JsonUtil.toBean(str, type);
            }

            Result<JsonNode> result = JsonUtil.toBean(str, new TypeReference<>() {
            });

            //如果返回错误，且为内部错误，则直接抛出异常
            if (result.fail()) {
                throw new GlobalException(result.getStatus(), result.getMsg());
            }

            if (result.getData() == null) {
                return null;
            }

            return JsonUtil.toBean(result.getData(), type);
        };
    }

    @Bean
    public RequestInterceptor interceptor() {
        return requestTemplate -> {

            MultiValueMap<String, String> headers = RequestThread.headers();

            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
                requestTemplate.header(entry.getKey(), entry.getValue());
            }
        };
    }

    public HttpMessageConverter<?> createJsonConverter() {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        jackson2HttpMessageConverter.setObjectMapper(JacksonUtil.createObjectMapper());
        return jackson2HttpMessageConverter;
    }


}
